// /////////////////////////////////////////////////////////////////////////////
//
// Name:            AssetManager.h
// Author:          Michael Bartsch (ZCCdark203)
//
// Desc :           Declaration of the AssetManager class.
//
// License:         Copyright (C) 2009 Michael Bartsch and Contributors
//
//                  This program is free software: you can redistribute it
//                  and/or modify it under the terms of the zlib/libpng License.
//                  See main.cpp for conditions of distribution and use.
//
// /////////////////////////////////////////////////////////////////////////////

#ifndef __ASSETMANAGAER_H__
#define __ASSETMANAGAER_H__

// Include files
#include "../dependencies.h"
#include "AssetGroup.h"
#include "AssetProcessor.h"

#include "../assets/processors.h"

// Forward declarations
class AssetGroup;
class AssetProcessor;


// AssetManager class
//! The AssetManager class manages the AssetGroups that are being used by the framework.
//! An asset managed by the AssetManager is only accessible through the AssetManager and
//! its related classes. That means that you can access assets through their respective
//! "normal" managers (i.e. meshes by Irrlicht's IMeshCache or entities by Sirrf's
//! EntityManager).
class AssetManager : public ReferenceCounted
{
    friend class AssetGroup;

public:

    // Initialisation and deinitialisation
    //! Constructor
    AssetManager();
    //! Deconstructor
    ~AssetManager();

    //! Initialises the AssetManager.
    void init();
    //! Clears the AssetManager.
    void clear();

    // Reference counting
    //! Increases the reference counter.
    //! @note This is a dummy function.
    void grab();
    //! Decreases the reference counter.
    //! @note This is a dummy function.
    void drop();

    // Methods
    //! Adds the given AssetGroup to the DataStore.
    //! @param group         Pointer to the AssetGroup to add.
    //! @return True if addition was successful, false if addition was a failure.
    bool addAssetGroup(AssetGroup *group);
    //! Creates (and adds) a AssetGroup with the given name.
    //! @param name          Name of the AssetGroup.
    //! @param dirName       Name of the base directory of the asset group.
    //! @param grab          Should the AssetsManager add the loaded asset group to the
    //!                      internal list?
    //! @return Pointer to the AssetGroup on success, NULL on failure.
    AssetGroup* createAssetGroup(const std::string &name, const std::string &dirName,
                                 bool grab = true);

    //! Gets the AssetGroup with the given ID.
    //! @return Pointer to the AssetGroup if found, else NULL.
    AssetGroup* getAssetGroup(const u32 id);
    //! Gets the AssetGroup with the given name.
    //! @return Pointer to the AssetGroup if found, else NULL.
    AssetGroup* getAssetGroup(const std::string &name);

    //! Registers an AssetProcessor factory function.
    //! @return True if addition was succesful, false if addition was a failure.
    bool registerProcessorFactory(const std::string &name, AssetProcessor* (*f)(AssetGroup*));
    //! Unregisters an AssetProcessor factory function.
    //! @return True if removal was successful, false if removal was a failure.
    bool unregisterProcessorFactory(const std::string &name);
    //! Unregisters all AssetProcessor factory functions.
    void unregisterProcessorFactories();

    //! Removes all AssetGroups from the AssetManager.
    void removeAssetGroups();
    //! Removes the given AssetGroup.
    //! @param group         Pointer to the AssetGroup to remove.
    //! @return True if removal was successful, false if removal was a failure.
    bool removeAssetGroup(AssetGroup *group);
    //! Removes the given AssetGroup with the given ID.
    //! @param id            ID of the AssetGroup to remove.
    //! @return True if removal was successful, false if removal was a failure.
    bool removeAssetGroup(const u32 id);
    //! Removes the given AssetGroup with the given name.
    //! @param name          Name of the AssetGroup to remove.
    //! @return True if removal was successful, false if removal was a failure.
    bool removeAssetGroup(const std::string &name);

private:

    // Private methods
    void getAssetProcessors(AssetGroup *group, std::vector<AssetProcessor*> &assetProcessors);

    // Normal members
    std::vector<AssetGroup*> mGroups;
    std::map<std::string, AssetProcessor* (*)(AssetGroup*)> mProcessorFactories;

};

#endif

